/*
 * LoginRequestPacket.java
 *
 * Created on May 12, 2007, 10:37 PM
 *************************************************************************
 * Copyright 2008 Paul Smith
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ao.protocol.packets.toserver;

import ao.protocol.packets.*;
import ao.protocol.packets.utils.PacketParser;
import ao.protocol.packets.utils.PacketSerializer;

import java.io.IOException;

/**
 * <p>LoginRequestPacket is sent from the client to the AO server
 * in an attempt to authenticate the client.</p>
 *
 * <p>PACKET TYPE: {@value #TYPE}
 * <br>FORMAT:      ISS
 * <br>DIRECTION:   out</p>
 *
 * @author Paul Smith
 * @see ao.protocol.packets.AOCharListPacket
 * @see ao.protocol.packets.AOLoginErrorPacket
 * @see ao.protocol.packets.AOLoginSeedPacket
 */
public class LoginRequestPacket extends Packet {
    
    public static final short TYPE = 2;
    
    private final int    m_version;
    private final String m_userName;
    private final String m_key;
    private final byte[] m_data;
    
    /** 
     * Creates a new instance of LoginRequestPacket
     *
     * @param version
     *        the version of the protocol to be utilized
     * @param userName
     *        the name of the account to attempt authentice the bot for
     * @param key
     *        an encrypted login key generated by 
     *        {@link ao.protocol.AOLoginKeyGenerator#generateLoginKey(String, String, String)}
     * @throws NullPointerException
     *         userName or key is null
     *
     * @see ao.protocol.AOLoginKeyGenerator#generateLoginKey(String, String, String)
     */
    public LoginRequestPacket(int version, String userName, String key) {
        if (userName == null) { throw new NullPointerException("No user name was passed."); }
        if (key      == null) { throw new NullPointerException("No key was passed."); }
        
        m_version  = version;
        m_userName = userName;
        m_key      = key;
        
        // Serialize the packet
        PacketSerializer serializer =
            new PacketSerializer( 8 + m_userName.length() + m_key.length() );
        serializer.write(m_version);
        serializer.write(m_userName);
        serializer.write(m_key);
        
        m_data = serializer.getResult();
        serializer.close();
    }   // end LoginRequestPacket()
    
    /** 
     * Creates a new instance of LoginRequestPacket
     *
     * @param data
     *        the binary data of this packet (without the type and length bytes)
     * @throws NullPointerException
     *         if data is null
     * @throws AOMalformedPacketException
     *         if the packet is malformed
     */
    public LoginRequestPacket(byte[] data) throws MalformedPacketException {
        if (data == null) { throw new NullPointerException("No binary data was passed."); }
        
        try {
            m_data                = data;
            PacketParser parser = new PacketParser(data);
        
            // Parse the packet
            m_version  = parser.parseInt();
            m_userName = parser.parseString();
            m_key      = parser.parseString();
        
            parser.close();
        } catch (IOException e) {
            throw new MalformedPacketException(
                "The packet could not be parsed.", e, new UnparsablePacket(TYPE, data, Direction.OUT)
            );
        }   // end catch
    }   // end LoginRequestPacket()
    
    /* Returns the version of the protocol to be utilized */
    public int getProtocolVersion() { return m_version; }
    /** Returns the name of the account to attempt authentice the bot for */
    public String getUserName() { return m_userName; }
    /** 
     * Returns an encrypted login key generated by 
     * {@link ao.protocol.AOLoginKeyGenerator#generateLoginKey(String, String, String)}
     */
    public String getKey() { return m_key; }
    
    /** Always returns {@value #TYPE} */
    public short getType() { return TYPE; }
    public byte[] getData() { return m_data; }
    /** Always returns {@code Direction.OUT} */
    public Direction getDirection() { return Direction.OUT; }
    
    @Override
    public String toString() {
        return "["+TYPE+"]LoginRequestPacket: " + getProtocolVersion() + ", " + getUserName() + ", " + getKey();
    }   // end toString()
    
}   // end class LoginRequestPacket
